package com.zx.sercurity.magiskdetector;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.system.Os;
import android.util.Log;

import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKey;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;

public class RemoteService extends Service {
    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        @Override
        public boolean haveSu() {
            return Native.haveSu() == 0;
        }

        @Override
        public boolean haveMagicMount() throws RemoteException {
            return Native.haveMagicMount() == 1;
        }

        @Override
        public boolean findMagiskdSocket() throws RemoteException {
            return Native.findMagiskdSocket() == 1;
        }

        @Override
        public boolean testIoctl() throws RemoteException {
            return Native.testIoctl() == 2;
        }

        @Override
        public boolean getPropsHash() throws RemoteException {
            return props() == 1;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        int appId = Os.getuid() % 100000;
        if (appId >= 90000) return mBinder;
        else return null;
    }

    private int props() {
        SharedPreferences sp;
        try {
            MasterKey masterKey = new MasterKey.Builder(this)
                    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                    .build();
            sp = EncryptedSharedPreferences.create(
                    this,
                    getPackageName(),
                    masterKey,
                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            );
        } catch (GeneralSecurityException | IOException e) {
            //Log.e(TAG, "Unable to open SharedPreferences.", e);
            return -1;
        }

        String spFingerprint = sp.getString("fingerprint", "");
        String fingerprint = Build.FINGERPRINT;
        //Log.i(TAG, "spFingerprint=" + spFingerprint + " \n  fingerprint=" + fingerprint);
        String spBootId = sp.getString("boot_id", "");
        String bootId = getBootId();
        //Log.i(TAG, "spBootId=" + spBootId + " \n  bootId=" + bootId);
        String spPropsHash = sp.getString("props_hash", "");
        if (spFingerprint.equals(fingerprint) && spBootId.length() > 0 && spPropsHash.length() > 0) {
            if (!spBootId.equals(bootId)) {
                return spPropsHash.equals(Native.getPropsHash()) ? 0 : 1;
            } else return 2;
        } else {
            SharedPreferences.Editor editor = sp.edit();
            editor.putString("fingerprint", fingerprint);
            editor.putString("boot_id", bootId);
            editor.putString("props_hash", Native.getPropsHash());
            editor.apply();
            return 2;
        }
    }


    private String getBootId() {
        String bootId = "";
        try (InputStream is = new FileInputStream("/proc/sys/kernel/random/boot_id")) {
            Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
            bootId = new BufferedReader(reader).readLine().trim();
        } catch (IOException e) {
            //Log.w(TAG, "Can't read boot_id.", e);
        }
        if (bootId.length() == 0) {
            bootId = String.valueOf((System.currentTimeMillis() - SystemClock.elapsedRealtime()) / 10);
        }
        return bootId;
    }
}
